package ocean.chinacraft.common.world.item.tool;

import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.BlockState;
import net.minecraft.block.IBucketPickupHandler;
import net.minecraft.block.ILiquidContainer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.BucketItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.Stats;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.event.ForgeEventFactory;
import ocean.chinacraft.common.ModItems;

import javax.annotation.Nonnull;
import java.util.function.Supplier;

/**
 * 木桶
 *
 * @author zhang
 * @since 2021/12/14
 */
public class WoodBucket extends BucketItem {

    private final Fluid content;

    public WoodBucket(Supplier<? extends Fluid> supplier, Item.Properties builder) {
        super(supplier, builder);
        this.content = supplier.get();
    }

    @Override
    public ActionResult<ItemStack> use(@Nonnull World world, PlayerEntity player, @Nonnull Hand hand) {
        ItemStack itemstack = player.getItemInHand(hand);
        BlockRayTraceResult hitResult = getPlayerPOVHitResult(world, player, content == Fluids.EMPTY ?
                RayTraceContext.FluidMode.SOURCE_ONLY : RayTraceContext.FluidMode.NONE);
        ActionResult<ItemStack> ret = ForgeEventFactory.onBucketUse(player, world, itemstack, hitResult);
        if (ret != null) {
            return ret;
        }
        if (hitResult.getType() == RayTraceResult.Type.MISS) {
            return ActionResult.pass(itemstack);
        } else if (hitResult.getType() != RayTraceResult.Type.BLOCK) {
            return ActionResult.pass(itemstack);
        } else {
            BlockPos blockpos = hitResult.getBlockPos();
            Direction direction = hitResult.getDirection();
            BlockPos blockpos1 = blockpos.relative(direction);
            if (world.mayInteract(player, blockpos) && player.mayUseItemAt(blockpos1, direction,
                    itemstack)) {
                if (this.content == Fluids.EMPTY) {
                    BlockState blockstate1 = world.getBlockState(blockpos);
                    if (blockstate1.getBlock() instanceof IBucketPickupHandler) {
                        Fluid fluid = ((IBucketPickupHandler) blockstate1.getBlock()).takeLiquid(world, blockpos
                                , blockstate1);
                        if (fluid != Fluids.EMPTY) {
                            player.awardStat(Stats.ITEM_USED.get(this));
                            SoundEvent soundevent = this.content.getAttributes().getFillSound();
                            if (soundevent == null) {
                                soundevent = fluid.is(FluidTags.LAVA) ? SoundEvents.BUCKET_FILL_LAVA :
                                        SoundEvents.BUCKET_FILL;
                            }
                            player.playSound(soundevent, 1.0F, 1.0F);
                            ItemStack itemstack1 = DrinkHelper.createFilledResult(itemstack, player,
                                    new ItemStack(ModItems.WOOD_WATER_BUCKET.get()));
                            if (!world.isClientSide) {
                                CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayerEntity) player,
                                        new ItemStack(fluid.getBucket()));
                            }

                            return ActionResult.sidedSuccess(itemstack1, world.isClientSide());
                        }
                    }
                    return ActionResult.fail(itemstack);
                } else {
                    BlockState blockstate = world.getBlockState(blockpos);
                    BlockPos blockpos2 = canBlockContainFluid(world, blockpos, blockstate) ? blockpos : blockpos1;
                    if (this.emptyBucket(player, world, blockpos2, hitResult)) {
                        this.checkExtraContent(world, itemstack, blockpos2);
                        if (player instanceof ServerPlayerEntity) {
                            CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, blockpos2,
                                    itemstack);
                        }

                        player.awardStat(Stats.ITEM_USED.get(this));
                        return ActionResult.sidedSuccess(this.getEmptySuccessItem(itemstack, player),
                                world.isClientSide());
                    } else {
                        return ActionResult.fail(itemstack);
                    }
                }
            } else {
                return ActionResult.fail(itemstack);
            }
        }
    }

    @Override
    protected ItemStack getEmptySuccessItem(ItemStack itemStack, PlayerEntity player) {
        return !player.abilities.instabuild ? new ItemStack(ModItems.WOOD_BUCKET.get()) : itemStack;
    }

    private boolean canBlockContainFluid(World worldIn, BlockPos posIn, BlockState blockstate) {
        return blockstate.getBlock() instanceof ILiquidContainer && ((ILiquidContainer) blockstate.getBlock()).canPlaceLiquid(worldIn, posIn, blockstate, this.content);
    }

    @Override
    public ItemStack getContainerItem(ItemStack itemStack) {
        return itemStack.copy();
    }

    @Override
    public boolean hasContainerItem(ItemStack stack) {
        return true;
    }
}
